using Sage.Http.Factory;
using System.Diagnostics.CodeAnalysis;
using System.Text.Json;
using System.Text.Json.Serialization.Metadata;

namespace Sage.Http.Utilities
{
    /// <summary>
    /// JSON序列化实用工具类，提供序列化和反序列化的便捷方法
    /// </summary>
    public static class JsonSerializerUtilities
    {
        /// <summary>
        /// 创建反序列化函数
        /// </summary>
        /// <typeparam name="T">目标类型</typeparam>
        /// <param name="jsonTypeInfo">JSON类型信息，用于AOT环境（推荐）</param>
        /// <param name="jsonOptions">自定义JSON序列化选项</param>
        /// <returns>反序列化函数</returns>
        /// <remarks>
        /// 在AOT环境中，建议提供jsonTypeInfo参数以启用源生成序列化。
        /// 如果同时提供了jsonTypeInfo和jsonOptions，将优先使用jsonTypeInfo。
        /// </remarks>
        [RequiresUnreferencedCode("JSON serialization and deserialization might require types that cannot be statically analyzed.")]
        [RequiresDynamicCode("JSON serialization and deserialization might require types that cannot be statically analyzed and might need runtime code generation.")]
        public static Func<string, T> CreateDeserializer<T>(
            JsonTypeInfo<T>? jsonTypeInfo = null,
            JsonSerializerOptions? jsonOptions = null)
        {
            // 优先使用AOT友好的JsonTypeInfo
            if (jsonTypeInfo != null)
            {
                return json => JsonSerializer.Deserialize(json, jsonTypeInfo)!;
            }

            // 获取有效的序列化选项
            var effectiveOptions = JsonSerializerOptionsFactory.GetEffectiveOptions(jsonOptions);

            return json => JsonSerializer.Deserialize<T>(json, effectiveOptions)!;
        }

        /// <summary>
        /// 尝试反序列化JSON字符串
        /// </summary>
        /// <typeparam name="T">目标类型</typeparam>
        /// <param name="json">JSON字符串</param>
        /// <param name="deserializer">反序列化函数</param>
        /// <param name="result">反序列化结果</param>
        /// <returns>如果反序列化成功返回true，否则返回false</returns>
        public static bool TryDeserialize<T>(
            string json,
            Func<string, T> deserializer,
            [NotNullWhen(true)] out T? result)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(json))
                {
                    result = default;
                    return false;
                }

                result = deserializer(json);
                return result != null;
            }
            catch
            {
                result = default;
                return false;
            }
        }

        /// <summary>
        /// 序列化对象为JSON字符串
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="value">要序列化的对象</param>
        /// <param name="jsonTypeInfo">JSON类型信息，用于AOT环境（推荐）</param>
        /// <param name="jsonOptions">自定义JSON序列化选项</param>
        /// <returns>JSON字符串</returns>
        /// <remarks>
        /// 在AOT环境中，建议提供jsonTypeInfo参数以启用源生成序列化。
        /// 如果同时提供了jsonTypeInfo和jsonOptions，将优先使用jsonTypeInfo。
        /// </remarks>
        [RequiresUnreferencedCode("JSON serialization and deserialization might require types that cannot be statically analyzed.")]
        [RequiresDynamicCode("JSON serialization and deserialization might require types that cannot be statically analyzed and might need runtime code generation.")]
        public static string Serialize<T>(
            T value,
            JsonTypeInfo<T>? jsonTypeInfo = null,
            JsonSerializerOptions? jsonOptions = null)
        {
            // 优先使用AOT友好的JsonTypeInfo
            if (jsonTypeInfo != null)
            {
                return JsonSerializer.Serialize(value, jsonTypeInfo);
            }

            // 获取有效的序列化选项
            var effectiveOptions = JsonSerializerOptionsFactory.GetEffectiveOptions(jsonOptions);

            return JsonSerializer.Serialize(value, effectiveOptions);
        }

        /// <summary>
        /// 尝试序列化对象为JSON字符串
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="value">要序列化的对象</param>
        /// <param name="result">序列化结果</param>
        /// <param name="jsonTypeInfo">JSON类型信息，用于AOT环境（推荐）</param>
        /// <param name="jsonOptions">自定义JSON序列化选项</param>
        /// <returns>如果序列化成功返回true，否则返回false</returns>
        [RequiresUnreferencedCode("JSON serialization and deserialization might require types that cannot be statically analyzed.")]
        [RequiresDynamicCode("JSON serialization and deserialization might require types that cannot be statically analyzed and might need runtime code generation.")]
        public static bool TrySerialize<T>(
            T value,
            [NotNullWhen(true)] out string? result,
            JsonTypeInfo<T>? jsonTypeInfo = null,
            JsonSerializerOptions? jsonOptions = null)
        {
            try
            {
                if (value == null)
                {
                    result = null;
                    return false;
                }

                result = Serialize(value, jsonTypeInfo, jsonOptions);
                return !string.IsNullOrEmpty(result);
            }
            catch
            {
                result = null;
                return false;
            }
        }

        /// <summary>
        /// 反序列化JSON字符串
        /// </summary>
        /// <typeparam name="T">目标类型</typeparam>
        /// <param name="json">JSON字符串</param>
        /// <param name="jsonTypeInfo">JSON类型信息，用于AOT环境（推荐）</param>
        /// <param name="jsonOptions">自定义JSON序列化选项</param>
        /// <returns>反序列化的对象</returns>
        /// <remarks>
        /// 在AOT环境中，建议提供jsonTypeInfo参数以启用源生成序列化。
        /// 如果同时提供了jsonTypeInfo和jsonOptions，将优先使用jsonTypeInfo。
        /// </remarks>
        [RequiresUnreferencedCode("JSON serialization and deserialization might require types that cannot be statically analyzed.")]
        [RequiresDynamicCode("JSON serialization and deserialization might require types that cannot be statically analyzed and might need runtime code generation.")]
        public static T? Deserialize<T>(
            string json,
            JsonTypeInfo<T>? jsonTypeInfo = null,
            JsonSerializerOptions? jsonOptions = null)
        {
            if (string.IsNullOrWhiteSpace(json))
            {
                return default;
            }

            // 优先使用AOT友好的JsonTypeInfo
            if (jsonTypeInfo != null)
            {
                return JsonSerializer.Deserialize(json, jsonTypeInfo);
            }

            // 获取有效的序列化选项
            var effectiveOptions = JsonSerializerOptionsFactory.GetEffectiveOptions(jsonOptions);

            return JsonSerializer.Deserialize<T>(json, effectiveOptions);
        }

        /// <summary>
        /// 尝试反序列化JSON字符串
        /// </summary>
        /// <typeparam name="T">目标类型</typeparam>
        /// <param name="json">JSON字符串</param>
        /// <param name="result">反序列化结果</param>
        /// <param name="jsonTypeInfo">JSON类型信息，用于AOT环境（推荐）</param>
        /// <param name="jsonOptions">自定义JSON序列化选项</param>
        /// <returns>如果反序列化成功返回true，否则返回false</returns>
        [RequiresUnreferencedCode("JSON serialization and deserialization might require types that cannot be statically analyzed.")]
        [RequiresDynamicCode("JSON serialization and deserialization might require types that cannot be statically analyzed and might need runtime code generation.")]
        public static bool TryDeserialize<T>(
            string json,
            [NotNullWhen(true)] out T? result,
            JsonTypeInfo<T>? jsonTypeInfo = null,
            JsonSerializerOptions? jsonOptions = null)
        {
            try
            {
                result = Deserialize(json, jsonTypeInfo, jsonOptions);
                return result != null;
            }
            catch
            {
                result = default;
                return false;
            }
        }
    }
}